/*!
\copyright  Copyright (c) 2020 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief
*/

#include "csip_set_member_advertising.h"

#include "le_advertising_manager.h"

#include <logging.h>
#include <panic.h>
#include <stdlib.h>

#define CSIP_SET_MEMBER_ADVERT_DATA_ITEMS       1
#define CSIP_SET_MEMBER_ADVERT_SIZE             8
#define CSIP_SET_MEMBER_PSRI_START_OCTECT       2
#define PSRI_SIZE                               6

static uint8 * current_psri = NULL;
static le_adv_item_data_t csip_set_member_advert;
static le_adv_item_handle csip_set_member_registered_handle = NULL;

static const uint8 csip_set_member_advert_data[CSIP_SET_MEMBER_ADVERT_SIZE] = {
    CSIP_SET_MEMBER_ADVERT_SIZE - 1,
    ble_ad_type_rsi_data,
    0,0,0,0,0,0,
};

static bool csipSetMember_GetItemData(le_adv_item_data_t * item)
{
    PanicNull(item);
    if(csip_set_member_advert.data)
    {
        if(memcmp(&csip_set_member_advert.data[CSIP_SET_MEMBER_PSRI_START_OCTECT], current_psri, PSRI_SIZE))
        {
            free((void *)csip_set_member_advert.data);
            csip_set_member_advert.data = NULL;
        }
    }
    if(csip_set_member_advert.data == NULL)
    {
        uint8 * data = PanicUnlessMalloc(CSIP_SET_MEMBER_ADVERT_SIZE);
        memcpy(data, csip_set_member_advert_data, CSIP_SET_MEMBER_ADVERT_SIZE);
        memcpy(&data[CSIP_SET_MEMBER_PSRI_START_OCTECT], current_psri, PSRI_SIZE);
        csip_set_member_advert.data = data;
        csip_set_member_advert.size = CSIP_SET_MEMBER_ADVERT_SIZE;
    }
    *item = csip_set_member_advert;
    return TRUE;
}

static void csipSetMember_ReleaseItemData(void)
{
    if(csip_set_member_advert.data)
    {
        free((void *)csip_set_member_advert.data);
        csip_set_member_advert.data = NULL;
    }
}

#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER

static bool csipSetMember_GetItemInfo(le_adv_item_info_t * info)
{
    PanicNull(info);
    *info = (le_adv_item_info_t){ .placement = le_adv_item_data_placement_advert,
                                    .type = le_adv_type_extended_connectable,
                                    .data_size = CSIP_SET_MEMBER_ADVERT_SIZE };
    return TRUE;
}

le_adv_item_callback_t csipSetMember_AdvertisingManagerCallback =
{
    .GetItemData = &csipSetMember_GetItemData,
    .ReleaseItemData = &csipSetMember_ReleaseItemData,
    .GetItemInfo = &csipSetMember_GetItemInfo
};

#else

static bool csipSetMember_CanAdvertise(const le_adv_data_params_t * params)
{
    bool can_advertise = FALSE;
    if(params->data_set == le_adv_data_set_extended_handset
            && params->completeness == le_adv_data_completeness_full
            && params->placement == le_adv_data_placement_advert)
    {
        can_advertise = TRUE;
    }
    return can_advertise;
}

static unsigned int csipSetMember_GetNumberOfAdvertisingItems(const le_adv_data_params_t * params)
{
    if (csipSetMember_CanAdvertise(params))
    {
        return CSIP_SET_MEMBER_ADVERT_DATA_ITEMS;
    }

    return 0;
}

static le_adv_data_item_t csipSetMember_GetAdvertisingData(const le_adv_data_params_t * params, unsigned int number)
{
    UNUSED(number);

    le_adv_data_item_t item;
    if(csipSetMember_CanAdvertise(params))
    {
        csipSetMember_GetItemData(&item);
        return item;
    }

    Panic();
    return item;
}

static void csipSetMember_ReleaseAdvertisingData(const le_adv_data_params_t * params)
{
    UNUSED(params);
    csipSetMember_ReleaseItemData();
}

le_adv_data_callback_t csipSetMember_AdvertisingManagerCallback =
{
    .GetNumberOfItems = &csipSetMember_GetNumberOfAdvertisingItems,
    .GetItem = &csipSetMember_GetAdvertisingData,
    .ReleaseItems = &csipSetMember_ReleaseAdvertisingData
};
#endif

bool CsipSetMember_SetupLeAdvertisingData(uint8 * psri)
{
    current_psri = psri;
#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER
    csip_set_member_registered_handle = LeAdvertisingManager_RegisterAdvertisingItemCallback(NULL, &csipSetMember_AdvertisingManagerCallback);
#else
    csip_set_member_registered_handle = LeAdvertisingManager_Register(NULL, &csipSetMember_AdvertisingManagerCallback);
#endif
    return (csip_set_member_registered_handle ? TRUE : FALSE);
}

bool CsipSetMember_UpdateLeAdvertisingData(uint8 * psri)
{
    free(current_psri);
    current_psri = psri;
#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER
    return (csip_set_member_registered_handle ? LeAdvertisingManager_UpdateAdvertisingItem(csip_set_member_registered_handle) : FALSE);
#else
    return (csip_set_member_registered_handle ? LeAdvertisingManager_NotifyDataChange(&ama_ble_task, csip_set_member_registered_handle) : FALSE);
#endif
}
